package io.potato.ts.service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import io.potato.core.CrudService;
import io.potato.core.util.SmsUtil;
import io.potato.core.util.Strings;
import io.potato.ts.common.Constants;
import io.potato.ts.common.SmsIdWorker;
import io.potato.ts.domain.SmsSendingRecord;
import io.potato.ts.domain.SmsUpRecord;
import io.potato.ts.domain.User;
import io.potato.ts.repository.SmsUpRecordRepository;
import lombok.extern.slf4j.Slf4j;


/**
 * 上行短信（已收到的短信）服务类
 * 
 * @author timl
 *
 * <p>2019-01-08 09:47:19</p>
 */
@Service
@Transactional
@Slf4j
public class SmsUpRecordService extends CrudService<SmsUpRecord, Integer> {

	@Autowired
	SmsUpRecordRepository repository;
	
	@Autowired
	SmsSendingRecordService ssrService;
	
	@Autowired
	SmsService smsService;
	
	@Autowired
	UserService userService;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	/**
	 * ID生成器
	 */
	@Autowired
	private SmsIdWorker idWorker;

	@Override
	protected JpaRepository<SmsUpRecord, Integer> getRepository() {
		return repository;
	}
	
	/**
	 * 接收用户回复的上行短信
	 * @param smsUpRecord
	 */
	public void receive(SmsUpRecord smsUpRecord) {
		String userCode = SmsUtil.getUserCode(smsUpRecord.getExtendCode());
		Integer userId = this.userService.findIdByCode(userCode);
		smsUpRecord.setUserId(userId);
		smsUpRecord.setUserCode(userCode);
		smsUpRecord.setMsgId("" + this.idWorker.nextId());  // 生成唯一ID
		
		// 保存上行短信
		save(smsUpRecord);
		
		// 自动回复短信
		reply(smsUpRecord, userId);
	}
	
	/**
	 * 回复发送人
	 * @param smsUpRecord
	 */
	private void reply(SmsUpRecord smsUpRecord, Integer userId) {
		if (SmsUtil.isWebUser(smsUpRecord.getExtendCode()) && userId != null) {
			// web用户才需要自动回复信息
			Optional<User> optionalUser = this.userService.findById(userId);
			if (optionalUser.isPresent()) {
				User user = optionalUser.get();
				
				if (StringUtils.isEmpty(user.getMobileNo())) {
					// 用户号码空的 不需要发送了
					return;
				}		
				
				String fromName = this.userService.findContractName(userId, smsUpRecord.getFromNum());
				String content = "来自" + fromName + "的回复：" + smsUpRecord.getContent();
				SmsSendingRecord sendingRec = ssrService.newWebSmsRecord(
						user.getUserCode(), user.getUserCode(), content, user.getMobileNo(), "自动回复", Constants.SmsType.REPLY, LocalDateTime.now());
				
				List<SmsSendingRecord> list = new ArrayList<>();
				list.add(sendingRec);
				this.smsService.submitBatchSms(user.getUserCode(), list);
			}
		}
	}
	
	/**
	 * 查询未读的上行短信
	 * @param extendCode 拓展码
	 * @return
	 */
	public List<SmsUpRecord> getUnReadUpSms(String extendCode) {	
		List<SmsUpRecord> list = repository.findUnRead(extendCode + "%");
		return list;
	}
	
	/**
	 * 跟新上行短信的查询次数， 每查询一次加1
	 * @param list  
	 */
	@Async
	public void updateReadTimesAsync(List<SmsUpRecord> list) {
		
		if (list == null || list.isEmpty()) {
			return;
		}
		
		// 更新查询次数
		List<Integer> ids = new ArrayList<Integer>();
		list.forEach(s -> ids.add(s.getId()));
		
		String sql = String.format("UPDATE sms_up_record SET read_times = read_times + 1 where id in (%s)", Strings.join(ids, ','));
		this.jdbcTemplate.update(sql);
	}
	
	/**
	 * 异步上行短信状态更新为已读
	 * @param msgIds
	 */
	@Async
	public void updateReadStatusAsync(List<String> msgIds) {
		List<String> ids = new ArrayList<String>();
		msgIds.forEach(s -> ids.add("'" + s + "'"));
		
		String sql = String.format("UPDATE sms_up_record SET read_times = 6 where msg_id IN (%s)", Strings.join(ids, ','));
		this.jdbcTemplate.update(sql);
	}
	
	/**
	 * 更新状态
	 * @param ids  ID
	 * @param status  状态  0 正常，  1 废弃
	 */
	public void updateStatus(List<Integer> ids, Integer status, Integer userId) {
		if (!Constants.UpRecordStatus.DISCARDED.equals(status)) {
			status = Constants.UpRecordStatus.NORMAL;
		}
		String sql = String.format("UPDATE sms_up_record SET status = ? where id in (%s) AND user_id = ? ", Strings.join(ids, ','));
		this.jdbcTemplate.update(sql, status, userId);
	}
	
	/**
	 * 删除用户所有废弃的记录
	 * @param userId  用户ID
	 */
	public void deleteByUserId(Integer userId) {
		String sql = "DELETE FROM sms_up_record WHERE user_id = ? AND status = 1";
		this.jdbcTemplate.update(sql, userId);
	}
	
	/**
	 * 根据条件查询已收短信列表
	 * @param pageable  分页
	 * @param userId  用户ID
	 * @param fromNo  发件人手机号码
	 * @param content  短信内容 模糊匹配
	 * @param start  开始日期
	 * @param end  结束日期
	 * @param status  状态  
	 * @return  分页列表
	 */
	public Page<Map<String, Object>> findUserUpRecord(
			Pageable pageable, Integer userId, 
			String fromNo, String content, LocalDateTime start, LocalDateTime end, Integer status) {
		
		String where = " t.user_id = " + userId;
		where += " AND status = " + status;
		
		List<Object> argList = new ArrayList<>();
		
		if (start != null) {
			where += " AND receive_time >= ?";
			argList.add(start);
		}
		
		if (end != null) {
			where += " AND receive_time < ?";
			argList.add(end);
		}
		
		if (!StringUtils.isEmpty(fromNo)) {
			where += " AND from_num like ?";
			argList.add(fromNo + "%");
		}
		
		if (!StringUtils.isEmpty(content)) {
			where += " AND content like ?";
			argList.add("%" + content + "%");
		}
		
		String sql = "select t.id, t.from_num fromNum, t.content, t.receive_time receiveTime, "
				+ "ifnull(t1.name,t2.real_name) fromName from \n" + 
				"sms_up_record t\n" + 
				"left join t_contacts t1\n" + 
				"on t.user_id = t1.user_id and t.from_num = t1.mobile_no \n" + 
				"left join t_user t2\n" + 
				"on t.from_num = t2.mobile_no \n" + 
				"where \n" + where +
 				" group by t.id limit " + 
				pageable.getOffset() + ", " + 
 				pageable.getPageSize();
		
		Object[] args = argList.toArray();
		List<Map<String, Object>> list = this.jdbcTemplate.queryForList(sql, args);
		
		String countSql = "select count(*) from sms_up_record t where " + where;
		long count = this.jdbcTemplate.queryForObject(countSql, args, Long.class);
		
		return new PageImpl<>(list, pageable, count);
	}
	
}
